package com.framework.service.common.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.framework.common.enums.menu.MenuTargetEnum;
import com.framework.common.model.response.R;
import com.framework.common.util.dataSource.DataSourceEncUtil;
import com.framework.common.util.minio.MinioUtil;
import com.framework.common.util.other.NumeralUtil;
import com.framework.common.util.other.SymbolUtil;
import com.framework.common.util.redis.RedisKeyUtil;
import com.framework.common.util.redis.RedisPrefixUtil;
import com.framework.model.common.vo.DataSourceConfigVo;
import com.framework.model.common.vo.DictVo;
import com.framework.model.system.vo.SystemMenuVo;
import com.framework.model.system.vo.SystemRoleMenuVo;
import com.framework.model.system.vo.SystemRoleVo;
import com.framework.model.system.vo.SystemUserVo;
import com.framework.service.base.BaseService;
import com.framework.service.common.CacheService;
import com.framework.service.common.DataSourceConfigService;
import com.framework.service.common.DictService;
import com.framework.service.system.SystemMenuService;
import com.framework.service.system.SystemRoleMenuService;
import com.framework.service.system.SystemRoleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author 龘鵺
 * @version 1.0
 * @className com.framework.service.common.impl
 * @description 缓存业务接口实现类
 * @datetime 2024-12-12 10:33:48
 */
@Service("cacheServiceImpl")
public class CacheServiceImpl extends BaseService implements CacheService {
    /**
     * 桶名称
     */
    @Value("${custom.minio.bucketName}")
    private String bucketName;
    @Autowired
    private SystemRoleService systemRoleServiceImpl;
    @Autowired
    private SystemMenuService systemMenuServiceImpl;
    @Autowired
    private SystemRoleMenuService systemRoleMenuServiceImpl;
    @Autowired
    private DictService dictServiceImpl;
    @Autowired
    private MinioUtil minioUtil;
    @Autowired
    private DefaultDataSourceCreator dataSourceCreator;
    @Autowired
    private DataSource dataSource;

    @Autowired
    private DataSourceConfigService dataSourceConfigServiceImpl;

    /**
     * @return com.framework.common.model.response.R
     * @title 刷新权限缓存
     * @description 刷新权限缓存
     * @author 龘鵺
     * @datetime 2024-12-12 10:33:48
     */
    @Override
    public R<?> refreshCache() {
        SystemUserVo systemUserVo = getUser();
        if (!super.ignoredRoleAuth.getAuthList().contains(systemUserVo.getRoleCode())) {
            return R.fail("无权限!");
        }
        initCache();
        return R.ok();
    }

    /**
     * @title 初始化权限缓存
     * @description 初始化权限缓存
     * @author 龘鵺
     * @datetime 2024-12-12 10:33:48
     */
    @Override
    public void initCache() {
        //清楚权限缓存开始
        String fuzzyKey = RedisPrefixUtil.REDIS_KEY_SYSTEM + SymbolUtil.NO_INPUT_METHOD_COLON + SymbolUtil.NO_INPUT_METHOD_ASTERISK;
        Set<String> keysSet = redisUtil.getKeys(fuzzyKey);
        if (keysSet != null) {
            redisUtil.deleteKey(keysSet);
        }
        //清楚权限缓存结束
//        SystemButton systemButton = new SystemButton();
//        systemButton.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ZERO);
//        List<SystemButton> buttonList = systemButtonServiceImpl.findByList(systemButton);

        SystemMenuVo button = new SystemMenuVo();
        button.setEnableStatus(NumeralUtil.POSITIVE_ONE);
        button.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ZERO);
        button.setCategory(NumeralUtil.POSITIVE_ONE);
        button.setType(NumeralUtil.POSITIVE_NINE_THOUSAND_NINE_HUNDRED_AND_NINETY_NINE);
        List<SystemMenuVo> buttonList = systemMenuServiceImpl.findByInitList(button);

        //查询菜单
        SystemMenuVo menu = new SystemMenuVo();
//        menu.setEnableStatus(NumeralUtil.POSITIVE_ONE);
        menu.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ZERO);
        menu.setCategory(NumeralUtil.POSITIVE_NINE_THOUSAND_NINE_HUNDRED_AND_NINETY_NINE);
        menu.setType(NumeralUtil.POSITIVE_NINE_THOUSAND_NINE_HUNDRED_AND_NINETY_NINE);
        List<SystemMenuVo> menuList = systemMenuServiceImpl.findByInitList(menu);

        SystemRoleVo systemRole = new SystemRoleVo();
        systemRole.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ZERO);
        List<SystemRoleVo> roleList = systemRoleServiceImpl.findByInitList(systemRole);

        List<SystemRoleMenuVo> roleMenuList = systemRoleMenuServiceImpl.findByInitList(null);
//        List<SystemRoleMenuButton> roleMenuButtonList = systemRoleMenuButtonServiceImpl.findByList(null);

        DictVo dictVo = new DictVo();
        dictVo.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ZERO);
        List<DictVo> sdList = dictServiceImpl.findByInitList(dictVo);


        //处理角色关联的菜单
        Map<Long, List<String>> srmMap = new HashMap<Long, List<String>>();
        Map<Long, List<SystemMenuVo>> srmMapList = new HashMap<Long, List<SystemMenuVo>>();
        Map<String, List<String>> srmbMap = new HashMap<String, List<String>>();
        for (SystemRoleMenuVo srm : roleMenuList) {//循环角色
            List<String> list = srmMap.get(srm.getRoleId());//判断当前map集合中的菜单代码集合
            List<SystemMenuVo> systemMenuList = srmMapList.get(srm.getRoleId());//判断当前map集合中的菜单代码集合

            if (list == null) {//菜单代码集合不存在就是第一次循环。
                list = new ArrayList<String>(menuList.size());//创建一个新的集合
            }
            if (systemMenuList == null) {//菜单集合不存在就是第一次循环。
                systemMenuList = new ArrayList<SystemMenuVo>(menuList.size());//创建一个新的集合
            }
            Iterator<SystemMenuVo> iteratorMenu = menuList.iterator();
            while (iteratorMenu.hasNext()) {
                //循环菜单
                SystemMenuVo sm = iteratorMenu.next();
                if (MenuTargetEnum.getCodeIsCache(sm.getTarget()) || sm.getEnableStatus().intValue() > NumeralUtil.POSITIVE_ONE) {
                    continue;
                }
                //匹配对应的角色菜单关联ID
                if (sm.getId().longValue() == srm.getMenuId().longValue() || srm.getMenuId().equals(sm.getId())) {
                    //匹配上了以后把菜单代码存入list集合中
                    list.add(sm.getCode());
                    systemMenuList.add(sm);
                    iteratorMenu.remove();
                }
            }
            Iterator<SystemMenuVo> iteratorButton = buttonList.iterator();
            while (iteratorButton.hasNext()) {
                //循环按钮
                SystemMenuVo sb = iteratorButton.next();
                //匹配对应的角色菜单关联ID
                if (sb.getParentId().longValue() == srm.getMenuId().longValue()) {
                    String menuButtonCode = srm.getRoleId() + "_" + sb.getParentId();
                    List<String> systemMenuButtonList = srmbMap.get(menuButtonCode);//判断当前map集合中的菜单代码集合
                    if (systemMenuButtonList == null) {//按钮集合不存在就是第一次循环。
                        systemMenuButtonList = new ArrayList<String>(NumeralUtil.POSITIVE_THIRTY);//创建一个新的集合
                    }
                    //匹配上了以后把菜单代码存入list集合中
                    systemMenuButtonList.add(sb.getCode());
                    srmbMap.put(menuButtonCode, systemMenuButtonList);
                    String menuButtonCode2 = srm.getMenuCode() + SymbolUtil.NO_INPUT_METHOD_COLON + sb.getCode();
                    redisUtil.setAuthButtonString(menuButtonCode2, JSONObject.toJSONString(sb));
                    iteratorButton.remove();
                }
            }
            //保存对应的角色ID键，菜单代码集合
            srmMap.put(srm.getRoleId(), list);
            srmMapList.put(srm.getRoleId(), systemMenuList);
        }

        //处理按钮
//        Map<String, List<String>> smbMap = new HashMap<String, List<String>>();s
//        List<String> buttonCodeList = null;
//        for (SystemMenuVo menuItem : menuList) {
//            buttonCodeList = new ArrayList<String>(NumeralUtil.POSITIVE_SIXTEEN);
//            Iterator<SystemMenuVo> it = buttonList.iterator();
//            while (it.hasNext()) {
//                //处理按钮权限，
//                SystemMenuVo sb = it.next();
//                //判断菜单和按钮关联
//                if (sb.getParentId().longValue() == menuItem.getId()) {
//                    buttonCodeList.add(sb.getCode());
//                    redisUtil.setAuthButtonString(sb.getCode(), JSONObject.toJSONString(sb));
////                    redisUtil.setAuthButtonString(sb.getUrl(), JSONObject.toJSONString(sb));
//                    it.remove();
//                }
//            }
//            if (buttonCodeList.size() > NumeralUtil.POSITIVE_ZERO) {
//                menuItem.setButtonCodeList(buttonCodeList);
//            }
////            //菜单缓存到redis
////            redisUtil.setAuthMenuString(menuItem.getCode(), JSONObject.toJSONString(menuItem));
//        }

        //{"buttonCodeList":["add","edit","del","password","upload","download","batchDel","lock","view","2"]

        //角色缓存到redis
        for (SystemRoleVo sr : roleList) {
            List<String> list = srmMap.get(sr.getId());
            sr.setMenuCodeList(list);
            redisUtil.setAuthRoleString(sr.getRoleCode(), JSONObject.toJSONString(sr));
            List<SystemMenuVo> systemMenuList = srmMapList.get(sr.getId());
            if (systemMenuList == null) {
                continue;
            }
            //菜单缓存到redis
            for (SystemMenuVo sm : systemMenuList) {
                String roleMenuCode = sr.getRoleCode() + SymbolUtil.NO_INPUT_METHOD_COLON + sm.getCode();
                String menuButtonCode = sr.getId() + "_" + sm.getId();
//                String roleMenuCode = sr.getRoleCode() + SymbolUtil.NO_INPUT_METHOD_COLON + sm.getUrl();
                List<String> buttonCodeList = srmbMap.get(menuButtonCode);
//                System.out.println(sr.getRoleCode() + "=" + sm.getCode() + ":" + JSONObject.toJSONString(buttonCodeList));
                sm.setButtonCodeList(buttonCodeList);
                redisUtil.setAuthMenuString(roleMenuCode, JSONObject.toJSONString(sm));
            }
        }
//        //菜单缓存到redis
//        for (SystemMenuVo sm : menuList) {
//            //按钮缓存到redis
//            for (SystemMenuVo sb : buttonList) {
//
//            }
//        }

        for (SystemMenuVo itemMenu : menuList) {
            Iterator<SystemMenuVo> iteratorButton = buttonList.iterator();
            while (iteratorButton.hasNext()) {
                //循环按钮
                SystemMenuVo sb = iteratorButton.next();
                //匹配对应的角色菜单关联ID
                if (sb.getParentId().longValue() == itemMenu.getId().longValue()) {
                    String menuButtonCode2 = itemMenu.getCode() + SymbolUtil.NO_INPUT_METHOD_COLON + sb.getCode();
                    redisUtil.setAuthButtonString(menuButtonCode2, JSONObject.toJSONString(sb));
                    iteratorButton.remove();
                }
            }
        }
        for (DictVo item : sdList) {
            redisUtil.setString(RedisKeyUtil.getPermissionDictKey(item.getDictKey()), JSONObject.toJSONString(item));
        }
    }

    /**
     * @return void
     * @title 项目初始化桶，避免上传异常
     * @description 项目初始化桶，避免上传异常
     * @author 龘鵺
     * @datetime 2024-12-12 10:33:48
     */
    @Override
    public void initCreateBucket() throws Exception {
        if (StringUtils.isNotEmpty(bucketName)) {
            minioUtil.createBucket(bucketName);
        }
    }

    /**
     * @title 初始化数据源
     * @description 初始化数据源
     * @author 龘鵺
     * @datetime 2025-05-06 14:49:38
     */
    @Override
    public void initDataSource() {
        DataSourceConfigVo dataSourceConfigVo = new DataSourceConfigVo();
        dataSourceConfigVo.setEnableStatus(NumeralUtil.POSITIVE_ONE);
        dataSourceConfigVo.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        List<DataSourceConfigVo> dataSourceConfigVoList = dataSourceConfigServiceImpl.findByList(dataSourceConfigVo);
        if (dataSourceConfigVoList.size() > NumeralUtil.POSITIVE_ZERO) {
            DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) dataSource;
            dataSourceConfigVoList.forEach(item -> {
                // 构建数据源属性
                DataSourceProperty property = new DataSourceProperty();
                property.setPoolName(item.getName());
                property.setUrl(item.getConnectAddress());
//                property.setUrl(DataSourceEncUtil.getEnc(item.getConnectAddress()));
                property.setUsername(DataSourceEncUtil.getEnc(item.getAccount()));
                property.setPassword(DataSourceEncUtil.getEnc(item.getPassword()));
                property.setDriverClassName(item.getDriverClass());
                // 开启懒加载。避免一次性申请太多连接
                property.setLazy(true);
                // 动态注册数据源
                DataSource dataSource = dataSourceCreator.createDataSource(property);
                dynamicRoutingDataSource.addDataSource(item.getCode(), dataSource);
//                dynamicRoutingDataSource.setP6spy();
//                dynamicRoutingDataSource.removeDataSource();
            });
        }
//        // 设置当前线程数据源
//        DynamicDataSourceContextHolder.push("slave_db");
//        // 执行数据库操作
//        DynamicDataSourceContextHolder.poll();
//        // 得到当前线程数据源
//        DynamicDataSourceContextHolder.peek();
//        // 强制清空本地线程
//        DynamicDataSourceContextHolder.clear();
    }
}
